package org.myabstract.graph.model.tests;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;
import org.myabstract.graph.model.IFilter;
import org.myabstract.graph.model.INodeType;
import org.myabstract.graph.model.Node;
import org.myabstract.graph.model.Reference;

public class NodeTests {

	private Node<INodeType> node1;
	private Node<INodeType> node2;
	private Node<INodeType> node3;

	private IFilter node3ChildrenFilter;
	private IFilter node3ParentFilter;

	private Reference<INodeType, INodeType> ref1;
	private Reference<INodeType, INodeType> ref2;
	private Reference<INodeType, INodeType> ref3;

	@Before
	public void setUp() {
		node1 = new Node<INodeType>(new Mock1NodeType());
		node2 = new Node<INodeType>(new Mock2NodeType());
		node3 = new Node<INodeType>(new MockNodeType());

		node3ChildrenFilter = new MockFilter();
		node3ParentFilter = new MockFilter();
		node3.setChildrenFilter(node3ChildrenFilter);
		node3.setParentFilter(node3ParentFilter);

		try {
			ref1 = new Reference<INodeType, INodeType>(node1, node2);
			ref2 = new Reference<INodeType, INodeType>(node2, node3);
			ref3 = new Reference<INodeType, INodeType>(node3, node1);

			node1.addReference(ref1);
			node1.addReference(ref3);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Test
	public void getTypeTestTrue() {
		assertTrue(Mock1NodeType.class.isInstance(node1.getType()));
	}

	@Test
	public void getTypeTestFalse() {
		assertTrue(Mock2NodeType.class.isInstance(node1.getType()) == false);
	}

	@Test
	public void findReferenceTestTrue() {
		Reference<INodeType, INodeType> aux = node1.findReference(node2
				.getType().getClass());
		assertEquals(ref1, aux);
	}

	@Test
	public void findReferenceTestFalse() {
		Reference<INodeType, INodeType> aux = node1.findReference(node2
				.getType().getClass());

		assertTrue(!aux.equals(ref2));
	}
 
	@Test
	public void findReferenceTestNull() {
		Reference<INodeType, INodeType> aux = node1
				.findReference(Mock3NodeType.class);
		assertEquals(null, aux);
	}

	@Test
	public void findReferenceNull() {
		Reference<INodeType, INodeType> aux = node1.findReference(null);
		assertEquals(null, aux);
	}

	@Test
	public void addReferenceTestTrue() {
		assertTrue(node3.addReference(ref3));
	}

	@Test
	public void addReferenceTestFalse() {
		assertTrue(node2.addReference(ref3) == false);
	}

	@Test
	public void addReferenceTestNull() {
		assertTrue(node3.addReference(null) == false);
	}

	@Test
	public void addReferenceTestDouble() {
		try {
			Reference ref4 = new Reference<INodeType, INodeType>(node1, node3);
			node3.addReference(ref3);
			node3.addReference(ref4);
			Reference res = node3.findReference(node1.getType().getClass());
			assertEquals(ref3, res);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Test
	public void deleteReferenceFalse() {
		node3.addReference(ref3);
		assertTrue(node3.deleteReference(ref2) == false);
	}

	@Test
	public void deleteReferenceNull() {
		node3.addReference(ref3);
		assertTrue(node3.deleteReference(null) == false);
	}

	@Test
	public void deleteReferenceTrue() {
		node3.addReference(ref3);
		assertTrue(node3.deleteReference(ref3) == true);
	}

	@Test
	public void deleteReferenceTrue2() {
		try {
			node3.addReference(ref3);
			Reference<INodeType, INodeType> ref4 = new Reference<INodeType, INodeType>(
					node1, node3);
			node3.addReference(ref4);
			assertTrue(node3.deleteReference(ref4) == true);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Test
	public void setFilterTest() {
		IFilter filter = new MockFilter();
		node1.setChildrenFilter(filter);
		assertEquals(filter, node1.getChildrenFilter());
	}

	@Test
	public void setFilterTestNull() {
		IFilter filter = new MockFilter();
		node1.setChildrenFilter(filter);

		node1.setChildrenFilter(null);
		assertEquals(filter, node1.getChildrenFilter());
	}

	@Test
	public void getFilterTest() {
		IFilter filter = new MockFilter();
		Node<INodeType> aux = new Node<INodeType>(new MockNodeType(), filter,
				null);
		assertEquals(filter, aux.getChildrenFilter());
	}

	// ////////// test for parent filter
	@Test
	public void setParentFilterTest() {
		IFilter filter = new MockFilter();
		node1.setParentFilter(filter);
		assertEquals(filter, node1.getParentFilter());
	}

	@Test
	public void setParentFilterTestNull() {
		IFilter filter = new MockFilter();
		node1.setParentFilter(filter);

		node1.setParentFilter(null);
		assertEquals(filter, node1.getParentFilter());
	}

	@Test
	public void getParentFilterTest() {
		IFilter filter = new MockFilter();
		Node<INodeType> aux = new Node<INodeType>(new MockNodeType(), null,
				filter);
		assertEquals(filter, aux.getParentFilter());
	}

	@Test
	public void getChildrenTest1() {
		node3.addReference(ref2);
		node3.addReference(ref3);
		Node<INodeType>[] res = node3.getChildren();
		Node<INodeType>[] exp = new Node[2];
		exp[0] = node2;
		exp[1] = node1;

		assertArrayEquals(exp, res);
	}

	@Test
	public void getChildrenTestFilterNull() {

		Node<INodeType>[] res = node2.getChildren();
		Node<INodeType>[] exp = new Node[0];

		assertArrayEquals(exp, node3.getChildren());
	}

	@Test
	public void getChildrenTest2() {
		Node<INodeType>[] exp = new Node[0];
		assertArrayEquals(exp, node2.getChildren());
	}

	@Test
	public void getParentTestNull() {
		node3.addReference(ref2);
		node3.addReference(ref3);
		assertEquals(null, node3.getParent());
	}

	@Test
	public void getParentTestTrue() {
		node3.addReference(ref2);
		assertEquals(node2, node3.getParent());
	}

	// filter null -> returns empty list
	@Test
	public void getParentTestNull1() {
		assertEquals(null, node2.getParent());
	}

	// /
	// @Test
	// public <T extends INodeType> void addReferencedElementTestTrue() {

	// node3.addReferencedElement(node2);
	// node3.addReferencedElement(node1);
	// node3.addReference(ref3);
	// node3.addReference(ref2);
	// List<?> lst = node3
	// .mockGetReferencedElements(node3.getChildrenFilter());

	// assertEquals(node2, lst.get(0));
	// assertEquals(node1, lst.get(1));
	// }

	// @Test
	// public void test1GetChildren() {
	// node3.addReferencedElement(node1);
	// node3.addReferencedElement(node2);
	// node3.addReference(ref3);
	//
	// Node<INodeType>[] list = node3.getChildren();
	// assertEquals(1, list.length);
	// assertEquals(node1, list[0]);
	// }
	//
	// @Test
	// public void test2GetChildren() {
	//
	// try {
	// node3.addReferencedElement(node1);
	// node3.addReferencedElement(node2);
	// node3.addReference(ref3);
	// Reference ref4 = new Reference<INodeType, INodeType>(node3, node2);
	// node3.addReference(ref4);
	//
	// Node<INodeType>[] list = node3.getChildren();
	// assertEquals(2, list.length);
	// Node<INodeType>[] result = new Node[2];
	// result[0] = node1;
	// result[1] = node2;
	// assertArrayEquals(result, list);
	//
	// } catch (Exception e) { // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// }
	//
	// @Test
	// public void test1GetParent() {
	// node3.addReferencedElement(node1);
	// node3.addReferencedElement(node2);
	// node3.addReference(ref3);
	//
	// Node<INodeType> parent = node3.getParent();
	// assertEquals(node1, parent);
	// }
	//
	// @Test
	// public void test2GetParent() {
	// try {
	// node3.addReferencedElement(node1);
	// node3.addReferencedElement(node2);
	// node3.addReference(ref3);
	// Reference ref4 = new Reference<INodeType, INodeType>(node3, node2);
	// node3.addReference(ref4);
	//
	// Node<INodeType> list = node3.getParent();
	// assertEquals(null, list);
	//
	// } catch (Exception e) { // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// }

}
